package net.siufung.security.provider;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import net.siufung.core.utils.GsonUtil;
import net.siufung.security.base.enums.TokenGranters;
import net.siufung.security.base.service.ICurrentUserService;
import net.siufung.security.provider.dto.PasswdLoginDto;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;

/**
 * 密码授权认证方式
 * @author 陈建峰
 * @since 2022/3/3 5:07 下午
 */
@Slf4j
@SuppressWarnings("deprecation")
public class PasswdAuthenticationGranter extends AbstractTokenGranter {

    private final AuthenticationManager authenticationManager;
    private final ICurrentUserService currentUserService;

    public PasswdAuthenticationGranter(
            AuthorizationServerTokenServices tokenServices,
            ClientDetailsService clientDetailsService,
            OAuth2RequestFactory requestFactory,
            AuthenticationManager authenticationManager,
            ICurrentUserService currentUserService) {
        super(tokenServices, clientDetailsService, requestFactory,
                TokenGranters.PASSWD.name().toLowerCase(Locale.ROOT));
        this.authenticationManager = authenticationManager;
        this.currentUserService = currentUserService;
    }

    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
        OAuth2Request oAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
        Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
        PasswdLoginDto passwdLoginDto = JSONObject.parseObject(
                JSON.toJSONString(parameters, SerializerFeature.BrowserCompatible),
                PasswdLoginDto.class);
        Authentication authentication = new PasswdAuthenticationToken(passwdLoginDto);
        ((AbstractAuthenticationToken) authentication).setDetails(parameters);
        authentication = authenticationManager.authenticate(authentication);
        if(authentication.isAuthenticated()){
            currentUserService.updateLoginInfo(passwdLoginDto.getLoginName(), TokenGranters.PASSWD,
                    GsonUtil.toGsonString(authentication.getDetails()));
        }
        return new OAuth2Authentication(oAuth2Request, authentication);
    }
}
